package com.ehotting.edsta.mqbd.signal.netty.handler;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.ehotting.eaf.core.StringHelper;
import com.ehotting.eaf.core.snow.SnowflakeUtil;
import com.ehotting.eaf.core.utils.StringUtils;
import com.ehotting.eaf.netty.action.Action;
import com.ehotting.eaf.netty.action.ActionAble;
import com.ehotting.eaf.netty.action.NettyActionFactory;
import com.ehotting.eaf.netty.client.TcpClient;
import com.ehotting.eaf.netty.constant.NettyConstant;
import com.ehotting.eaf.netty.constant.NettyState;
import com.ehotting.eaf.netty.domain.DataAble;
import com.ehotting.eaf.netty.domain.Response;
import com.ehotting.eaf.netty.loggers.NettyMsgReceiveLogger;
import com.ehotting.eaf.netty.sync.SyncFutureMapHelper;
import com.ehotting.edsta.mqbd.api.enums.SysModuleEnum;
import com.ehotting.mqbd.core.logger.LOGGER_KEY;
import com.ehotting.mqbd.core.manager.AgentLinkManager;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;

@Sharable
public class SiClientNettyHandler extends SimpleChannelInboundHandler<String> {
	
	protected final Logger logger = LoggerFactory.getLogger(this.getClass());
	
	protected NettyActionFactory nettyActionFactory;
	protected TcpClient tcpClient;
	protected NettyMsgReceiveLogger nettyMsgReceiveLogger;
	protected SyncFutureMapHelper<DataAble> siSyncFutureMapHelper;
	protected AgentLinkManager agentLinkManager;

	@Override
	protected void channelRead0(ChannelHandlerContext ctx, String data) throws Exception {
		MDC.put(LOGGER_KEY.MODULE,SysModuleEnum.SIGNAL_ANALYSIS.getCode());
		MDC.put(LOGGER_KEY.TRACE_ID, SnowflakeUtil.nextId64());
		nettyMsgReceiveLogger.info(data);
		DataAble response = null;
		String serial = null;
		try{
			JSONObject requestJson = JSON.parseObject(data, JSONObject.class, Feature.OrderedField);
			/**处理业务**/
			String action = (String)requestJson.get(NettyConstant.ACTION);
			if(StringUtils.isBlank(action)){
				logger.error("action is null,data is {},return.",data);
				return;
			}

			ActionAble<DataAble> nettyAction = nettyActionFactory.getAction(action);
			if(nettyAction == null){
				logger.error("nettyAction[{},action={}] is null,return.",ctx.channel().remoteAddress(),action);
				return;
			}
			
			DataAble request =(DataAble) JSONObject.parseObject(data,nettyAction.getRequestClass());
			Action actionType = nettyAction.getClass().getAnnotation(Action.class);
			if(siSyncFutureMapHelper!=null && (actionType==null || actionType.isNotice())
					&& (request!=null && StringUtils.hasText(request.getSerial()))){
				siSyncFutureMapHelper.putAndNotify(request.getSerial(), request);
			}
			setOtherProp( request,ctx);
			response = nettyAction.invoke(ctx,request);
		}catch(Exception e){
			logger.error("data:{}",data);
			logger.error("nettyAction invoke error",e);
			response = new Response(NettyState.ACTION_EXCETION,NettyState.FAIL,serial,e.getMessage());
		}finally{
			/**返回数据**/
			if(response!=null){
				String result =  JSON.toJSONString(response, SerializerFeature.DisableCircularReferenceDetect);
//				logger.info("result:{}",result);
				ctx.writeAndFlush(result);
			}
			MDC.clear();
		}
	}

	private void setOtherProp(DataAble request,ChannelHandlerContext ctx){
		String channelId = ctx.channel().id().asLongText();
		String agentId = agentLinkManager.getAgentIdByChannelId(SysModuleEnum.SIGNAL_ANALYSIS.getCode(),channelId);
		if(StringHelper.isBlank(agentId)){
			logger.error("Get agentId[channelId={}] is null,close tcp.",channelId);
			agentLinkManager.deleteAgentIdByChannelId(SysModuleEnum.SIGNAL_ANALYSIS.getCode(),channelId);
			tcpClient.shutdown();
			return;
		}

		request.setFrom(agentId);
		request.setUserId(agentLinkManager.getUserId(agentId));
		String clientIp = agentLinkManager.getClientIpByAgentId(agentId);
		if(StringHelper.isBlank(clientIp)){
			logger.error("Get clientIp[agentId={}] is null,close tcp.",agentId);
			agentLinkManager.deleteAgentIdByChannelId(SysModuleEnum.SIGNAL_ANALYSIS.getCode(),channelId);
			tcpClient.shutdown();
			return;
		}
		request.setDevice(clientIp);
	}

   @Override
    public void channelActive(ChannelHandlerContext ctx) {
	   logger.info(ctx.channel().remoteAddress() + "   ----Active");
    }
    
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)throws Exception {
    	logger.info("Unexpected exception from downstream." + cause);
		cause.printStackTrace();
		ctx.close().addListener(ChannelFutureListener.CLOSE);
    }
    
    @Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception {
    	super.channelInactive(ctx);
    	tcpClient.doConnect();
	}

	public void setNettyActionFactory(NettyActionFactory nettyActionFactory) {
		this.nettyActionFactory = nettyActionFactory;
	}

	public void setTcpClient(TcpClient tcpClient) {
		this.tcpClient = tcpClient;
	}

	public void setNettyMsgReceiveLogger(NettyMsgReceiveLogger nettyMsgReceiveLogger) {
		this.nettyMsgReceiveLogger = nettyMsgReceiveLogger;
	}

	public void setSiSyncFutureMapHelper(SyncFutureMapHelper<DataAble> siSyncFutureMapHelper) {
		this.siSyncFutureMapHelper = siSyncFutureMapHelper;
	}

	public void setAgentLinkManager(AgentLinkManager agentLinkManager) {
		this.agentLinkManager = agentLinkManager;
	}


}